home *** CD-ROM | disk | FTP | other *** search
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __QUICKDRAW__
- #include <Quickdraw.h>
- #endif
-
- #ifndef __WINDOWS__
- #include <Windows.h>
- #endif
-
- #include "ZoomCode.h"
-
- /*
- Change History, Fabrizio Oddone
-
- 97/04/15 Window macros accessors, FO
-
- 97/04/11 UPP modification was buggy, FO
- Eliminated stuff conflicting with new Windows.h, FO
-
- 12/07/94 modified by James E. Trudeau
- Now uses a UPP for call to DeviceLoop()
- */
-
- enum {
- kNudgeSlop = 2, // I like 2 better, FO
- kIconSpace = 64
- };
-
- static pascal void CalcWindowAreaOnScreen(short depth, short deviceFlags, GDHandle targetDevice,
- long userData);
- static short CalculateOffsetAmount(short idealStartPoint, short idealEndPoint,
- short idealOnScreenStartPoint, short idealOnScreenEndPoint,
- short screenEdge1, short screenEdge2);
-
- static void GetWindowPortRect(WindowPeek theWindow, Rect * const portRect);
- static void ContentRect2DefaultStructRect(Rect * const strucR);
-
-
- /*
- WindowRecord accessor functions
- */
-
- // macros instead of functions;
- // I didn't use the Windows.h accessors because
- // they call CopyRgn(), so you'd need to DisposeRgn() later -- FO
-
- #define GetWContentRegion(w) (w->contRgn)
- #define GetWStructureRegion(w) (w->strucRgn)
-
- void ZoomTheWindow(WindowPeek theWindow, short zoomState,
- CalcIdealDocumentSizeProcPtr calcRoutine,
- CalcIdealDocumentSizeProcPtr postProcess)
- {
- ZoomData zoomData;
- Rect newStandardRect;
- Rect scratchRect;
- Rect screenRect;
- Rect portRect;
- Rect contentRegionBoundingBox;
- Rect structureRegionBoundingBox;
- GrafPtr currentPort;
- short horizontalAmountOffScreen;
- short verticalAmountOffScreen;
- short windowFrameTopSize;
- short windowFrameLeftSize;
- short windowFrameRightSize;
- short windowFrameBottomSize;
-
-
- GetPort(¤tPort);
- SetPort((WindowPtr) theWindow);
- GetWindowPortRect(theWindow, &portRect);
-
- if (nil == GetWContentRegion(theWindow) || EmptyRgn(GetWContentRegion(theWindow))) {
- contentRegionBoundingBox = portRect;
- LocalToGlobal(&topLeft(contentRegionBoundingBox));
- LocalToGlobal(&botRight(contentRegionBoundingBox));
- }
- else
- contentRegionBoundingBox = (**GetWContentRegion(theWindow)).rgnBBox;
-
- if (nil == GetWStructureRegion(theWindow) || EmptyRgn(GetWStructureRegion(theWindow))) {
- structureRegionBoundingBox = contentRegionBoundingBox;
- ContentRect2DefaultStructRect(&structureRegionBoundingBox);
- }
- else
- structureRegionBoundingBox = (**GetWStructureRegion(theWindow)).rgnBBox;
-
- // Determine the size of the window frame
- windowFrameTopSize = contentRegionBoundingBox.top -
- structureRegionBoundingBox.top;
- windowFrameLeftSize = contentRegionBoundingBox.left -
- structureRegionBoundingBox.left;
- windowFrameRightSize = structureRegionBoundingBox.right -
- contentRegionBoundingBox.right;
- windowFrameBottomSize = structureRegionBoundingBox.bottom -
- contentRegionBoundingBox.bottom;
-
- // If the window is being zoomed into the standard state, calculate the best size
- // to display the window’s information.
- if (zoomState == inZoomOut) {
- GDHandle mainDevice;
-
- mainDevice = GetParentScreenRect(theWindow, &zoomData, &screenRect);
- // Go figure out the perfect size for the window as if we had an infinitely large
- // screen
- calcRoutine((WindowPtr) theWindow, &newStandardRect);
-
- // Anchor the new rectangle at the window’s current top left corner
- OffsetRect(&newStandardRect, -newStandardRect.left, -newStandardRect.top);
- OffsetRect(&newStandardRect, contentRegionBoundingBox.left,
- contentRegionBoundingBox.top);
-
- // newStandardRect is the ideal size for the content area. The window frame
- // needs to be accounted for when we see if the window needs to be moved,
- // or resized, so add in the dimensions of the window frame.
- newStandardRect.top -= windowFrameTopSize;
- newStandardRect.left -= windowFrameLeftSize;
- newStandardRect.right += windowFrameRightSize;
- newStandardRect.bottom += windowFrameBottomSize;
-
- // If the new rectangle falls off the edge of the screen, nudge it so that it’s just
- // on the screen. CalculateOffsetAmount determines how much of the window is offscreen.
- SectRect(&newStandardRect, &screenRect, &scratchRect);
- if (!EqualRect(&newStandardRect, &scratchRect)) {
- horizontalAmountOffScreen = CalculateOffsetAmount(newStandardRect.left,
- newStandardRect.right,
- scratchRect.left,
- scratchRect.right,
- screenRect.left,
- screenRect.right);
- verticalAmountOffScreen = CalculateOffsetAmount(newStandardRect.top,
- newStandardRect.bottom,
- scratchRect.top,
- scratchRect.bottom,
- screenRect.top,
- screenRect.bottom);
- OffsetRect(&newStandardRect, horizontalAmountOffScreen, verticalAmountOffScreen);
- }
-
- // If we’re still falling off the edge of the screen, that means that the perfect
- // size is larger than the screen, so we need to shrink down the standard size
- SectRect(&newStandardRect, &screenRect, &scratchRect);
- if (!EqualRect(&newStandardRect, &scratchRect)) {
-
- // First shrink the width of the window. If the window is wider than the screen
- // it is zooming to, we can just pin the standard rectangle to the edges of the
- // screen, leaving some slop. If the window is narrower than the screen, we know
- // we just nudged it into position, so nothing needs to be done.
- if ((newStandardRect.right - newStandardRect.left) >
- (screenRect.right - screenRect.left)) {
- newStandardRect.left = screenRect.left + kNudgeSlop;
- newStandardRect.right = screenRect.right - kNudgeSlop;
-
- if ((zoomData.screenWithLargestPartOfWindow == mainDevice) &&
- (newStandardRect.right > (screenRect.right - kIconSpace)))
- newStandardRect.right = screenRect.right - kIconSpace;
- }
-
- // Move in the top. Like the width of the window, nothing needs to be done unless
- // the window is taller than the height of the screen.
- if ((newStandardRect.bottom - newStandardRect.top) >
- (screenRect.bottom - screenRect.top)) {
- newStandardRect.top = screenRect.top + kNudgeSlop;
- newStandardRect.bottom = screenRect.bottom - kNudgeSlop;
- }
- }
-
- // We’ve got the best possible window position. Remove the
- // frame, slam it into the WStateData record and let ZoomWindow
- // take care of the rest.
- newStandardRect.top += windowFrameTopSize;
- newStandardRect.left += windowFrameLeftSize;
- newStandardRect.right -= windowFrameRightSize;
- newStandardRect.bottom -= windowFrameBottomSize;
- if (postProcess)
- postProcess((WindowPtr)theWindow, &newStandardRect);
- SetWindowStandardState(theWindow, &newStandardRect);
- }
- else
- GetWindowUserState(theWindow, &newStandardRect);
-
- // If the window is still anchored at the current location, then just resize it
- if ((newStandardRect.left == contentRegionBoundingBox.left) &&
- (newStandardRect.top == contentRegionBoundingBox.top)) {
- OffsetRect(&newStandardRect, -newStandardRect.left, -newStandardRect.top);
- SizeWindow((WindowPtr) theWindow, newStandardRect.right, newStandardRect.bottom, true);
- }
- else {
- RgnHandle scratchRegion;
-
- scratchRegion = NewRgn();
- GetClip(scratchRegion);
- ClipRect(&portRect);
- EraseRect(&portRect);
- ZoomWindow((WindowPtr) theWindow, zoomState, false);
- SetClip(scratchRegion);
- DisposeRgn(scratchRegion);
- }
-
- SetPort(currentPort);
- }
-
- pascal void CalcWindowAreaOnScreen(short depth, short deviceFlags, GDHandle targetDevice, long userData)
- {
- #pragma unused (depth, deviceFlags)
- ZoomDataPtr zoomData = (ZoomDataPtr) userData;
- long windowAreaOnScreen;
- Rect windowPortionOnScreen;
-
- // Find the rectangle that encloses the intersection of the window and this screen.
- SectRect(&(zoomData->windowBounds), &((**targetDevice).gdRect), &windowPortionOnScreen);
-
- // Offset the rectangle so that it’s right and bottom are also it’s width and height.
- OffsetRect(&windowPortionOnScreen, -windowPortionOnScreen.left, -windowPortionOnScreen.top);
-
- // Calculate the area of the portion of the window that’s on this screen.
- windowAreaOnScreen = (long) windowPortionOnScreen.right * (long) windowPortionOnScreen.bottom;
-
- // If this is the largest portion of the window that has been encountered so far,
- // remember this screen as the potential screen to zoom to.
- if (windowAreaOnScreen > zoomData->largestArea) {
- zoomData->largestArea = windowAreaOnScreen;
- zoomData->screenWithLargestPartOfWindow = targetDevice;
- }
- }
-
- // Figure out how much we need to move the window to get it entirely on the monitor. If
- // the window wouldn’t fit completely on the monitor anyway, don’t move it at all; we’ll
- // make it fit later on.
-
- short CalculateOffsetAmount(short idealStartPoint, short idealEndPoint, short idealOnScreenStartPoint,
- short idealOnScreenEndPoint, short screenEdge1, short screenEdge2)
- {
- short offsetAmount;
-
- // First check to see if the window fits on the screen in this dimension.
- if ((idealStartPoint < screenEdge1) && (idealEndPoint > screenEdge2))
- offsetAmount = 0;
- else {
-
- // Find out how much of the window lies off this screen by subtracting the amount of the window
- // that is on the screen from the size of the entire window in this dimension. If the window
- // is completely offscreen, the offset amount is going to be the distance from the ideal
- // starting point to the first edge of the screen.
- if ((idealOnScreenStartPoint - idealOnScreenEndPoint) == 0) {
- // See if the window is lying to the left or above the screen
- if (idealEndPoint < screenEdge1)
- offsetAmount = screenEdge1 - idealStartPoint + kNudgeSlop;
- else
- // Otherwise, it’s below or to the right of the screen
- offsetAmount = screenEdge2 - idealEndPoint - kNudgeSlop;
- }
- else {
- // Window is already partially or completely on the screen
- offsetAmount = (idealEndPoint - idealStartPoint) -
- (idealOnScreenEndPoint - idealOnScreenStartPoint);
-
- // If we are offscreen a little, move the window in a few more pixels from the edge of the screen.
- if (offsetAmount != 0)
- offsetAmount += kNudgeSlop;
- // Check to see which side of the screen the window was falling off of, so that it can be
- // nudged in the opposite direction.
- if (idealEndPoint > screenEdge2)
- offsetAmount = -offsetAmount;
- }
- }
-
- return offsetAmount;
- }
-
- /*
- WindowRecord accessor functions
- */
-
-
- void GetWindowPortRect(WindowPeek theWindow, Rect * const portRect)
- {
- *portRect = theWindow->port.portRect;
- }
-
-
- GDHandle GetParentScreenRect(WindowPeek w, ZoomDataPtr zd, Rect * const screenRect)
- {
- GDHandle mainDevice;
- RgnHandle scratchRegion;
-
- #if GENERATING68K
- long Gresp;
- if (Gestalt(gestaltQuickdrawVersion, &Gresp) == noErr && Gresp >= gestalt32BitQD13) {
- #endif
- { Rect globalPortRect;
-
- mainDevice = GetMainDevice();
- zd->screenWithLargestPartOfWindow = mainDevice;
- zd->largestArea = 0;
-
- // Usually, we would use the content region’s bounding box to determine the monitor
- // with largest portion of the window’s area. However, if the entire content region
- // of the window is not on any screen, the structure region should be used instead.
- GetWindowPortRect(w, &globalPortRect);
- LocalToGlobal(&topLeft(globalPortRect));
- LocalToGlobal(&botRight(globalPortRect));
-
- scratchRegion = NewRgn();
- RectRgn(scratchRegion, &globalPortRect);
- SectRgn(GetGrayRgn(), scratchRegion, scratchRegion);
- zd->windowBounds = globalPortRect;
- }
- if (EmptyRgn(scratchRegion)) {
- if (nil == GetWStructureRegion(w) || EmptyRgn(GetWStructureRegion(w))) {
- ContentRect2DefaultStructRect(&zd->windowBounds);
- }
- else
- zd->windowBounds = (*GetWStructureRegion(w))->rgnBBox;
- }
-
- // Use DeviceLoop to walk through all the active screens to find the one with the
- // largest portion of the zoomed window
- { Rect localPortRect;
-
- localPortRect = zd->windowBounds;
- GlobalToLocal(&topLeft(localPortRect));
- GlobalToLocal(&botRight(localPortRect));
- RectRgn(scratchRegion, &localPortRect);
- }
- /* jt 12/7/94 for PPC, replace original call to DeviceLoop to use UPP */
- // FO 97/04/11 fix UPP
- {
- DeviceLoopDrawingUPP myUPP = NewDeviceLoopDrawingProc(CalcWindowAreaOnScreen);
-
- DeviceLoop(scratchRegion, myUPP, (long) zd, (DeviceLoopFlags) singleDevices);
-
- DisposeRoutineDescriptor(myUPP);
- }
-
- DisposeRgn(scratchRegion);
- *screenRect = (*zd->screenWithLargestPartOfWindow)->gdRect;
- #if GENERATING68K
- }
- else {
- zd->screenWithLargestPartOfWindow = mainDevice = (GDHandle)-1;
- *screenRect = qd.screenBits.bounds;
- }
- #endif
-
-
- // If the monitor being zoomed to is the main monitor, change the top of the
- // usable screen area to avoid putting the title bar underneath the menubar.
- if (zd->screenWithLargestPartOfWindow == mainDevice)
- screenRect->top += GetMBarHeight();
- return mainDevice;
- }
-
- void ContentRect2DefaultStructRect(Rect * const strucR)
- {
- strucR->top -= 19;
- strucR->left -= 1;
- strucR->bottom += 2;
- strucR->right += 2;
- }
-
-